package com.plexobject.rbac.service.impl; import java.util.Date; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.apache.log4j.Logger; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import com.plexobject.rbac.cache.CacheFlusher; import com.plexobject.rbac.http.RestClient; import com.plexobject.rbac.jmx.JMXRegistrar; import com.plexobject.rbac.jmx.impl.ServiceJMXBeanImpl; import com.plexobject.rbac.metric.Metric; import com.plexobject.rbac.metric.Timing; import com.plexobject.rbac.service.ServerStatusService; import com.plexobject.rbac.service.impl.ServerStatusServiceImpl; import com.plexobject.rbac.utils.TimeUtils; @Path("/status") @Component("serverStatusService") @Scope("singleton") public class ServerStatusServiceImpl implements ServerStatusService { private static final Logger LOGGER = Logger .getLogger(ServerStatusServiceImpl.class); @Context UriInfo uriInfo; final ServiceJMXBeanImpl mbean; private static final long STARTED = TimeUtils.getCurrentTimeMillis(); public ServerStatusServiceImpl() { mbean = JMXRegistrar.getInstance().register(getClass()); } /* * (non-Javadoc) * * @see com.plexobject.rbac.service.CacheFlushService#flushCaches() */ @Override @DELETE @Consumes( { MediaType.WILDCARD }) public Response flushCaches() { try { CacheFlusher.getInstance().flushCaches(); mbean.incrementRequests(); return Response.ok().build(); } catch (Exception e) { LOGGER.error("failed to flush caches", e); mbean.incrementError(); return Response.status(RestClient.SERVER_INTERNAL_ERROR).type( "text/plain").entity( "failed to flush caches due to " + e + "\n").build(); } } /* * (non-Javadoc) * * @see com.plexobject.rbac.service.CacheFlushService#flushCaches() */ @Override @GET @Consumes( { MediaType.WILDCARD }) public Response cacheSizes() { final JSONObject response = new JSONObject(); try { response.put("started", new Date(STARTED)); response.put("uptime", uptime()); response.put("cacheSizes", getCacheSizes()); response.put("metrics", getMetrics()); response.put("systemStats", Timing.getSystemStats()); response.put("serviceJMXBeans", getServiceJMXBeans()); if (uriInfo != null) { response.put("baseUrl", uriInfo.getAbsolutePath().toString()); } mbean.incrementRequests(); } catch (JSONException e) { LOGGER.error("failed to get stats", e); mbean.incrementError(); return Response.status(RestClient.SERVER_INTERNAL_ERROR).type( "text/plain").entity( "failed to get stats due to " + e + "\n").build(); } return Response.ok(response.toString()).build(); } private JSONArray getMetrics() { final JSONArray metrics = new JSONArray(); for (Metric m : Metric.getMetrics()) { metrics.put(m.toString()); } return metrics; } private JSONArray getServiceJMXBeans() { final JSONArray jmx = new JSONArray(); for (ServiceJMXBeanImpl m : JMXRegistrar.getInstance() .getServiceJMXBeans()) { jmx.put(m.toString()); } return jmx; } private JSONArray getCacheSizes() { final JSONArray sizes = new JSONArray(); int[] size = CacheFlusher.getInstance().cacheSizes(); for (int i = 0; i < size.length; i++) { sizes.put(String.valueOf(size[i])); } return sizes; } private static String uptime() { final long elapsed = TimeUtils.getCurrentTimeMillis() - STARTED; return elapsed > 1000 ? String.format("%.2f secs", elapsed / 1000) : String.format("%.2f millis", elapsed); } }